package com.company.Lock;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;

// 10分钟 -- 15分钟 给你写 JUC锁 给你
// 分析原理
public class MyLock {
    // 锁的状态 0-未占用  大于0 -占用
    AtomicInteger state = new AtomicInteger(); // juc 针对 int 做的封装
    // 锁的拥有者 标记
    Thread owner = null;
    // 当前在等待抢锁的线程
    LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>();

    // 尝试加锁，立刻返回结果
    public boolean tryLock() {
        if (state.get() == 0) {// 如果没人加锁，从0改为1代表加锁成功
            if (state.compareAndSet(0, 1)) { // 底层 CAS 比较和替换
                owner = Thread.currentThread(); // 当前执行这段代码的线程
                return true;
            }
        }
        return false;
    }

    // 抢锁，没抢到 等待
    public void lock(){
        if(!waiters.isEmpty() || !tryLock()) {// 你要公平怎么办？ --- 要判断是否有排队
            waiters.add(Thread.currentThread()); //  加入等待队列,以后会抢锁
            while (true) {
                if(Thread.currentThread() == waiters.peek() && tryLock()) {
                    waiters.poll();// 从队列移除第一个 // 抢锁了 --- 从等待集合移除
                    return;
                } else {
                    LockSupport.park();// 等待 -- 调用lock方法的这个线程不要跑 --- 唤醒后 再次抢锁
                }
            }
        }
    }

    // 释放锁 --- 只能够由锁的拥有者
    public void unlock(){
        if(Thread.currentThread() != owner) {
            throw new RuntimeException("不是你的锁，你要瞎动手");
        }

        if(state.decrementAndGet() == 0) { // 等于把 状态 i--， -- 0代表锁未被占用
            owner = null;
            // 如何通知？
            Thread waiterThread = waiters.peek();// 从等待队列 获取第一个 -- 排在第一个
            if(waiterThread != null) {
                LockSupport.unpark(waiterThread);
            }
        }
    }

}
